﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace msBsc.AppLogic.Cfg
{
    [Serializable]
    public class SynDictionary : IDisposable
    {
        
        //在.NET的对象中实际上有两个用于释放资源的函数：Dispose和Finalize。Finalize的目的是用于释放非托管的资源，而Dispose是用于释放所有资源，包括托管的和非托管的。
        
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!m_disposed)
            {
                if (disposing)
                {
                    // Release managed resources
                    if (_isSynchronized)
                    {
                        innerCacheHash.Clear();
                    }
                    else
                    {
                        innerCacheDic.Clear();
                    }
                }

                // Release unmanaged resources

                m_disposed = true;
            }
        }

        ~SynDictionary()
        {
            Dispose(false);
        }

        private bool m_disposed;

        //public void Dispose()
        //{
        //    this.Dispose(true);////释放托管资源
        //}
        //protected virtual void Dispose(bool disposing)
        //{
        //    if (disposing)
        //    {
        //        if (_isSynchronized)
        //        {
        //            innerCacheHash.Clear();
        //        }
        //        else
        //        {
        //            innerCacheDic.Clear();
        //        }
        //        GC.SuppressFinalize(this);//请求系统不要调用指定对象的终结器. //该方法在对象头中设置一个位，系统在调用终结器时将检查这个位
        //    }
        //}
        //~SynDictionary()
        //{
        //    this.Dispose(true);//有可能开发人员忘记调用Dispose方法，导致资源泄漏，为了避免这种情况，在析构函数调用Dispose,确保资源被释放
        //} 


        //如果是从列表中查询结果，用for循环比linq快,如果要对结果进行Distinct操作，linq快，Contains、union等数组操作相当耗时 List性能优于Dictionary,堆栈用System.Collections.Queue mySyncdQ = System.Collections.Queue.Synchronized(new System.Collections.Queue())    要尽量排除错误，不要用try catch
        //string[] 大多数情况下用count()比length快,List<string>比用string[]快,字符窜split最慢
        //private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
        //private Dictionary<string, object> innerCache = new Dictionary<string, object>();
        private Dictionary<string, object> innerCacheDic;
        private Hashtable innerCacheHash;
        private bool _isSynchronized = false;
        public bool isSynchronized
        {
            get
            {
                return _isSynchronized;
            }
        }
        //public SynDictionary()
        //{
        //    innerCacheDic =new Dictionary<string,object>();
        //}
        public SynDictionary(bool _pisSynchronized)
        {
            if (_pisSynchronized)
            {
                Hashtable myHT = new Hashtable();
                innerCacheHash = Hashtable.Synchronized(myHT);
            }
            else
            {
                innerCacheDic = new Dictionary<string, object>();
            }
            _isSynchronized = _pisSynchronized;
        }


        public object this[string key]
        {
            get
            {
                return Read(key);
            }
            set
            {
                Add(key, value);
            }
        }
        public object this[int i]
        {
            get
            {
                if (Keys.Count() > i)
                {
                    return Read(Keys[i]);
                }
                return null;
            }
            set
            {
                if (Keys.Count() > i)
                {
                    Add(Keys[i], value);
                }
            }
        }

        public void Clear()
        {
            if (_isSynchronized)
            {
                innerCacheHash.Clear();
            }
            else
            {
                innerCacheDic.Clear();
            } 
        }

        //public Dictionary<string, object> GetDictionary()
        //{
        //    return innerCache;
        //}

        private  object Read(string key)
        {
            if (key == null || key == string.Empty)
            {
                return null;
            }
            if (_isSynchronized)
            {
                if (!this.innerCacheHash.ContainsKey(key))
                {
                    return null;
                }
                else
                {
                    return innerCacheHash[key];
                }
            }
            else
            {
                if (!this.innerCacheDic.ContainsKey(key))
                {
                    return null;
                }
                else
                {
                    return innerCacheDic[key];
                }
            }
        }

        public bool ContainsKey(string key)
        {
            if (key == null || key == string.Empty)
            {
                return false;
            }
            if (_isSynchronized)
            {
                return this.innerCacheHash.ContainsKey(key);
            }
            else
            {
                return this.innerCacheDic.ContainsKey(key);
            }
        }

        public int Count 
        {
            get
            {
                if (_isSynchronized)
                {
                    return this.innerCacheHash.Count;
                }
                else
                {
                    return this.innerCacheDic.Count;
                }
            }
        }

        public string[] Keys
        {
            get
            {
                if (_isSynchronized)
                {
                    string[] arrtem1=new string[innerCacheHash.Count];
                    this.innerCacheHash.Keys.CopyTo(arrtem1, 0);
                    return arrtem1;
                }
                else
                {
                    return this.innerCacheDic.Keys.ToArray();
                }
            }
        }

        public object[] Values
        {
            get
            {
                if (_isSynchronized)
                {
                    object[] arrtem1 = new object[innerCacheHash.Count];
                    this.innerCacheHash.Values.CopyTo(arrtem1, 0);
                    return arrtem1;
                }
                else
                {
                    return this.innerCacheDic.Values.ToArray();
                }
            }
        }

        private object objlock = new object();
        public void Add(string key, object value)
        {
            if (key == null || key == string.Empty)
            {
                return ;
            }
            if (_isSynchronized)
            {
                innerCacheHash[key] = value;
            }
            else
            {
                if (!this.innerCacheDic.ContainsKey(key))
                {
                    innerCacheDic.Add(key, value);
                }
                else
                {
                    innerCacheDic[key] = value;
                }
            }
            
            ////开始一个非事务范围   
            //using (System.Transactions.TransactionScope scope2 = new System.Transactions.TransactionScope(
            //    System.Transactions.TransactionScopeOption.Suppress))
            //{
            //    try
            //    {
            //        innerCache.Add(key, value);
            //    }
            //    catch
            //    {
            //        innerCache[key] = value;
            //    }
            //}


            //lock (objlock)
            //{
            //    if (innerCache.ContainsKey(key))
            //    {
            //        innerCache[key] = value;
            //    }
            //    else
            //    {
            //        innerCache.Add(key, value);
            //    }
            //}
            //cacheLock.EnterWriteLock();
            //try
            //{
            //    innerCache.Add(key, value);
            //}
            //finally
            //{
            //    cacheLock.ExitWriteLock();
            //}
        }

        //public bool AddWithTimeout(string key, object value, int timeout)
        //{
        //    if (cacheLock.TryEnterWriteLock(timeout))
        //    {
        //        try
        //        {
        //            innerCache.Add(key, value);
        //        }
        //        finally
        //        {
        //            cacheLock.ExitWriteLock();
        //        }
        //        return true;
        //    }
        //    else
        //    {
        //        return false;
        //    }
        //}

        //public AddOrUpdateStatus AddOrUpdate(string key, object value)
        //{
        //    cacheLock.EnterUpgradeableReadLock();
        //    try
        //    {
        //        object result = null;
        //        if (innerCache.TryGetValue(key, out result))
        //        {
        //            if (result == value)
        //            {
        //                return AddOrUpdateStatus.Unchanged;
        //            }
        //            else
        //            {
        //                cacheLock.EnterWriteLock();
        //                try
        //                {
        //                    innerCache[key] = value;
        //                }
        //                finally
        //                {
        //                    cacheLock.ExitWriteLock();
        //                }
        //                return AddOrUpdateStatus.Updated;
        //            }
        //        }
        //        else
        //        {
        //            cacheLock.EnterWriteLock();
        //            try
        //            {
        //                innerCache.Add(key, value);
        //            }
        //            finally
        //            {
        //                cacheLock.ExitWriteLock();
        //            }
        //            return AddOrUpdateStatus.Added;
        //        }
        //    }
        //    finally
        //    {
        //        cacheLock.ExitUpgradeableReadLock();
        //    }
        //}


        public void Delete(string key)
        {
            if (key == null || key == string.Empty)
            {
                return;
            }
            if (_isSynchronized)
            {
                if (innerCacheHash.ContainsKey(key))
                {
                    innerCacheHash[key] = null;
                    innerCacheHash.Remove(key);
                }
            }
            else
            {
                if (this.innerCacheDic.ContainsKey(key))
                {
                    innerCacheDic[key] = null;
                    innerCacheDic.Remove(key);
                }
            }

            //cacheLock.EnterUpgradeableReadLock();
            //try
            //{ 
            //    if (innerCache.ContainsKey(key))
            //    {
            //        cacheLock.EnterWriteLock();
            //        try
            //        {
            //            innerCache.Remove(key);
            //        }
            //        finally
            //        {
            //            cacheLock.ExitWriteLock();
            //        }
            //    }
            //}
            //finally
            //{
            //    cacheLock.ExitUpgradeableReadLock();
            //}
        }

        //public enum AddOrUpdateStatus
        //{
        //    Added,
        //    Updated,
        //    Unchanged
        //};
    }

}